/*
 * Copyright(C) 2019 FUYUN DATA SERVICES CO.,LTD. - All Rights Reserved
 * Unauthorized copying of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 * 该源代码版权归属福韵数据服务有限公司所有
 * 未经授权，任何人不得复制、泄露、转载、使用，否则将视为侵权
 */

import axios from "axios";
import Cookies from "js-cookie";
/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
interface Ioptions {
  authorToken?: string | undefined;
  authorSet?: boolean;
  method: string;
  isFormData?: boolean;
  headers?: object;
  data: object;
  body?: string | object;
  [propName: string]: any;
}

// 类型保护
function typeProtect(obj: string | object | undefined) {
  return typeof obj === "object" ? obj : {};
}

export default function request(url: string, options: Ioptions) {
  const token: string | undefined = Cookies.get("user_token");
  const { authorSet = false, authorToken } = options;
  const defaultOptions = authorSet
    ? {
        credentials: "include",
        timeout: 50000,
        headers: { Authorization: authorToken }
      }
    : {
        credentials: "include",
        headers: {
          Authorization: token
        },
        timeout: 50000
      };
  const newOptions = { ...defaultOptions, ...options };
  if (
    newOptions.method === "POST" ||
    newOptions.method === "PUT" ||
    newOptions.method === "PATCH"
  ) {
    if (newOptions.isFormData) {
      const formData = new FormData();
      Object.keys(typeProtect(newOptions.data)).map((item, index) => {
        formData.append(item, typeProtect(newOptions.data)[item]);
      });
      newOptions.headers = {
        "Content-Type": "multipart/form-data"
      };
      newOptions.data = formData;
    } else {
      newOptions.headers = {
        Accept: "application/json",
        "Content-Type": "application/json;charset=UTF-8",
        ...newOptions.headers
      };
      newOptions.body = JSON.stringify(newOptions.body);
    }
  }

  return axios(url, newOptions)
    .then(response => {
      const { status, statusText, headers } = response;
      let { data } = response;
      if (typeof data !== "object") {
        data = {
          data
        };
      }
      return Promise.resolve({
        status,
        statusText,
        headers,
        data
      });
    })
    .catch(error => {
      if (error.response) {
        const { status, statusText, headers } = error.response;
        let { data } = error.response;
        if (typeof data !== "object") {
          data = {
            data
          };
        }
        return Promise.resolve({
          status,
          statusText,
          headers,
          ...data,
          data
        });
      } else {
        return Promise.resolve({
          status: 500
        });
      }
    });
}
